﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Net.Mail;
using System.Xml;
using System.Xml.Linq;
using CYP.IISMonitor.Utility.Log;

namespace CYP.IISMonitor.Utility.Mails
{
    /// <summary>
    /// 邮件发送
    /// </summary>
    public class SendMail
    {
        /// <summary>
        /// 当前服务
        /// </summary>
        private static string currentServer = string.Empty;   //判断是否改变了发送服务器需要

        /// <summary>
        /// 锁
        /// </summary>
        private static object _lock = new object();

        /// <summary>
        /// 发送邮件实例
        /// </summary>
        private static SendMail _instance = null;

        /// <summary>
        /// 日志
        /// </summary>
        private readonly TextLogger _log = TextLogManager.Create(typeof(SendMail));

        /// <summary>
        /// 发送人
        /// </summary>
        private string strFrom = "fromwho";

        /// <summary>
        /// host
        /// </summary>
        private string strHost = "smtp.exmail.qq.com";

        /// <summary>
        /// 端口
        /// </summary>
        private int intPort = 25;

        /// <summary>
        /// 用户名
        /// </summary>
        private string strUserName = "xxxxxx@xxx.xxx";

        /// <summary>
        /// 密码
        /// </summary>
        private string strPassword = "xxxxxx";

        /// <summary>
        /// 显示名
        /// </summary>
        /// <value>显示名</value>
        public string DisplayName { get; set; } //显示的发件人的名字

        /// <summary>
        /// 邮件发送构造函数
        /// </summary>
        /// <param name="mailServer">邮件服务</param>
        private SendMail(string mailServer)
        {
            string path = string.Empty;
            if (System.Web.HttpContext.Current != null)
            {
                path = System.Web.HttpContext.Current.Server.MapPath("~/MailConfig.xml");
            }
            else
            {
                path = AppDomain.CurrentDomain.BaseDirectory + "MailConfig.xml";
            }

            XDocument po = XDocument.Load(path);
            IEnumerable<XElement> ls = from el in po.Descendants("sendAcount")
                                       where el.Attribute("mailServer").Value.Trim().ToLower() == mailServer.Trim().ToLower()
                                       select el;

            foreach (XElement item in ls)
            {
                strFrom = item.Element("from").Value;
                strHost = item.Element("host").Value;
                intPort = Convert.ToInt32(item.Element("port").Value);
                strUserName = item.Element("userName").Value;
                strPassword = item.Element("password").Value;
            }
        }

        /// <summary>
        /// 根据mailServer属性进行区分，调用MailConfig.xml中配置的那个节点
        /// </summary>
        /// <param name="mailServer">MailConfig.xml中配置的发送服务器名称</param>
        /// <returns>邮件发送实例</returns>
        public static SendMail GetInstance(string mailServer)
        {
            if (_instance == null || currentServer != mailServer)
            {
                lock (_lock)
                {
                    currentServer = mailServer;
                    _instance = new SendMail(mailServer);
                }
            }

            return _instance;
        }

        /// <summary>
        /// 发送邮件(TXT格式)
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">邮件</param>
        /// <param name="sBody">邮件内容</param>
        public void SendTxt(string sSubject, string sEmail, string sBody)
        {
            MailMessage MailObj = new MailMessage(strFrom, sEmail, sSubject, sBody);
            MailObj.SubjectEncoding = Encoding.GetEncoding(936);
            MailObj.BodyEncoding = Encoding.GetEncoding(936);
            MailObj.HeadersEncoding = Encoding.GetEncoding(936);
            SmtpClient SmtpClients = new SmtpClient(strHost, intPort);
            SmtpClients.Credentials = new System.Net.NetworkCredential(strUserName, strPassword);
            if (!string.IsNullOrEmpty(DisplayName))
            {
                MailObj.From = new MailAddress(strFrom, DisplayName);
            }
            //SmtpClients.EnableSsl = true;
            try
            {
                SmtpClients.Send(MailObj);
            }
            catch
            {
            }

            MailObj.Dispose();
        }

        /// <summary>
        /// 邮件格式
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">接收人</param>
        /// <param name="sBody">内容</param>
        public void SendHtml(string sSubject, string sEmail, string sBody)
        {
            MailMessage MailObj = new MailMessage(strFrom, sEmail, sSubject, sBody);
            MailObj.IsBodyHtml = true;
            MailObj.SubjectEncoding = Encoding.GetEncoding(936);
            MailObj.BodyEncoding = Encoding.GetEncoding(936);
            MailObj.HeadersEncoding = Encoding.GetEncoding(936);
            SmtpClient SmtpClients = new SmtpClient(strHost, intPort);
            SmtpClients.Credentials = new System.Net.NetworkCredential(strUserName, strPassword);
            if (!string.IsNullOrEmpty(DisplayName))
            {
                MailObj.From = new MailAddress(strFrom, DisplayName);
            }

            //SmtpClients.EnableSsl = true;
            try
            {
                SmtpClients.Send(MailObj);
            }
            catch
            {
            }

            MailObj.Dispose();
        }

        /// <summary>
        /// 发送抄送邮件
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">收件人</param>
        /// <param name="sBody">内容</param>
        /// <param name="emailCC">抄送人</param>
        public void SendHtmlByCC(string sSubject, string sEmail, string sBody, string emailCC)
        {
            MailMessage MailObj = new MailMessage(strFrom, sEmail, sSubject, sBody);
            if (!string.Empty.Equals(emailCC))
            {
                MailObj.CC.Add(emailCC);
            }

            MailObj.IsBodyHtml = true;
            MailObj.SubjectEncoding = Encoding.GetEncoding(936);
            MailObj.BodyEncoding = Encoding.GetEncoding(936);
            MailObj.HeadersEncoding = Encoding.GetEncoding(936);
            SmtpClient SmtpClients = new SmtpClient(strHost, intPort);
            SmtpClients.Credentials = new System.Net.NetworkCredential(strUserName, strPassword);
            if (!string.IsNullOrEmpty(DisplayName))
            {
                MailObj.From = new MailAddress(strFrom, DisplayName);
            }

            try
            {
                SmtpClients.Send(MailObj);
            }
            catch
            {
            }

            MailObj.Dispose();
        }

        #region 异步方法

        /// <summary>
        /// 异步发送邮件 【内容为html格式】
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">邮箱号码</param>
        /// <param name="sBody">内容</param>
        public void SendAsyncHtml(string sSubject, string sEmail, string sBody)
        {
            SendAsync(sSubject, sEmail, sBody, true, string.Empty);
        }

        /// <summary>
        /// 异步发送邮件 【内容为text格式】
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">邮箱号码</param>
        /// <param name="sBody">内容</param>
        public void SendAsyncTxt(string sSubject, string sEmail, string sBody)
        {
            SendAsync(sSubject, sEmail, sBody, false, string.Empty);
        }

        /// <summary>
        /// 异步发送邮件 【内容为html格式】
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">邮箱号码</param>
        /// <param name="sBody">内容</param>
        /// <param name="emailCC">抄送邮箱</param>
        public void SendAsyncHtmlByCC(string sSubject, string sEmail, string sBody, string emailCC)
        {
            SendAsync(sSubject, sEmail, sBody, true, emailCC);
        }

        /// <summary>
        /// 异步发送邮件 【内容为text格式】
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">邮箱号码</param>
        /// <param name="sBody">内容</param>
        /// <param name="emailCC">抄送邮箱</param>
        public void SendAsyncTxtByCC(string sSubject, string sEmail, string sBody, string emailCC)
        {
            SendAsync(sSubject, sEmail, sBody, false, emailCC);
        }

        /// <summary>
        /// 异步发送
        /// </summary>
        /// <param name="sSubject">主题</param>
        /// <param name="sEmail">邮箱号码</param>
        /// <param name="sBody">内容</param>
        /// <param name="isHtml">是否是html格式</param>
        /// <param name="emailCC">抄送邮箱</param>
        private void SendAsync(string sSubject, string sEmail, string sBody, bool isHtml, string emailCC)
        {
            MailMessage MailObj = new MailMessage(strFrom, sEmail, sSubject, sBody)
            {
                IsBodyHtml = isHtml,
                //SubjectEncoding = Encoding.GetEncoding(936),
                //BodyEncoding = Encoding.GetEncoding(936),
                //HeadersEncoding = Encoding.GetEncoding(936)
            };
            //_log.Info("MailMessage");
            if (!string.IsNullOrEmpty(emailCC))
            {
                MailObj.CC.Add(emailCC);
            }

            SmtpClient SmtpClients = new SmtpClient(strHost, intPort);
            SmtpClients.Credentials = new System.Net.NetworkCredential(strUserName, strPassword);
            if (!string.IsNullOrEmpty(DisplayName))
            {
                MailObj.From = new MailAddress(strFrom, DisplayName);
            }

            try
            {
                SmtpClients.SendCompleted += SendCompletedCallback;
                SmtpClients.SendAsync(MailObj, sEmail);
            }
            catch
            {
                _log.Info("Result = false;");
            }
        }

        /// <summary>
        /// 发送回调
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="e">参数</param>
        private void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
        {
            string token = e.UserState.ToString();
            //_log.Info("token:"+token);
            if (e.Cancelled)
            {
                _log.Info("{0} Send canceled.", token);
            }

            if (e.Error != null)
            {
                _log.Info("邮件发送失败，发送目标：{0}.错误信息：{1}", token, e.Error.Message);
            }
        }

        #endregion
    }
}
